package com.frank.loadinglibrary.common.element;

import com.frank.loadinglibrary.base.baseanimations.BaseAnimationController;
import com.frank.loadinglibrary.base.baseelement.BaseElement;
import com.frank.loadinglibrary.base.baseelement.IComponentCallback;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.render.*;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;

import java.util.ArrayList;

/**
 * @author SUQI
 * @date 2021/6/2
 * @description
 **/
public class RingGradientElement extends BaseElement implements BaseAnimationController.IAnimationController<Animator> {

    private Paint mPaint;
    private float mRadius;
    private RectFloat rectF;
    private float strokeWidth;
    private boolean isFill;
    private float startAngle;
    private float sweepAngle;
    private Color startColor;
    private Color endColor;
    private Color[] colors;
    private int duration;

    private RingGradientElement(IComponentCallback callback) {
        this.callback = callback;
    }

    @Override
    public ArrayList<Animator> onCreateAnimators() {
        ArrayList<Animator> list = new ArrayList<>();
        AnimatorProperty animatorProperty = callback.getAnimatorProperty();
        animatorProperty
                .rotate(360)
                .setDuration(duration)
                .setLoopedCount(Animator.INFINITE)
                .start();
        list.add(animatorProperty);
        return list;
    }

    @Override
    public void onAnimationReset() {
        //do nothing because donot need to reset animation params
    }

    @Override
    public void initPaint() {
        super.initPaint();
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(strokeWidth);
        mPaint.setStyle(isFill ? Paint.Style.FILL_STYLE : Paint.Style.STROKE_STYLE);
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        mRadius = Math.min(mHeight, mWidth) / 2;
        Shader shader = new SweepShader(mWidth / 2, mHeight / 2, colors, null);
        mPaint.setShader(shader, Paint.ShaderType.SWEEP_SHADER);
        rectF = new RectFloat(strokeWidth, mHeight / 2 - mRadius  + strokeWidth, mWidth - strokeWidth, mHeight / 2 + mRadius  - strokeWidth);
        canvas.drawArc(rectF, new Arc(startAngle, sweepAngle, false), mPaint);
    }

    @Override
    public BaseAnimationController.IAnimationController<Animator> initAnimationController() {
        return this;
    }

    private void config(RingGradientBuilder builder) {
        this.strokeWidth = builder.strokeWidth;
        this.isFill = builder.isFill;
        this.startAngle = builder.startAngle;
        this.sweepAngle = builder.sweepAngle;
        this.startColor = builder.startColor;
        this.endColor = builder.endColor;
        this.colors = new Color[]{this.startColor, this.endColor};
        this.duration = builder.duration;
        initPaint();
    }

    public static class RingGradientBuilder {
        private IComponentCallback iComponentCallback;
        private float strokeWidth = 10;
        private boolean isFill = false;
        private float startAngle = 0;
        private float sweepAngle = 270;
        private Color startColor = Color.WHITE;
        private Color endColor = Color.TRANSPARENT;
        private int duration = 2000;

        public RingGradientBuilder(IComponentCallback iComponentCallback) {
            this.iComponentCallback = iComponentCallback;
        }

        public RingGradientBuilder setStrokeWidth(float strokeWidth) {
            this.strokeWidth = strokeWidth;
            return this;
        }

        public RingGradientBuilder setFill(boolean fill) {
            isFill = fill;
            return this;
        }

        public RingGradientBuilder setStartAngle(float startAngle) {
            this.startAngle = startAngle;
            return this;
        }

        public RingGradientBuilder setSweepAngle(float sweepAngle) {
            this.sweepAngle = sweepAngle;
            return this;
        }

        public RingGradientBuilder setStartColor(Color startColor) {
            this.startColor = startColor;
            return this;
        }

        public RingGradientBuilder setEndColor(Color endColor) {
            this.endColor = endColor;
            return this;
        }

        public RingGradientBuilder setDuration(int duration) {
            this.duration = duration;
            return this;
        }

        public RingGradientElement build() {
            RingGradientElement ringGradientElement = new RingGradientElement(iComponentCallback);
            ringGradientElement.config(this);
            return ringGradientElement;
        }
    }
}
